#include "Bin.h"

/**
 * \fn	Bin::Bin(int startX, int startY, BinColor binColor)
 *
 * \brief	Constructor.
 *
 * \author	Andrew
 * \date	11/11/2011
 *
 * \param	startX  	The start x coordinate.
 * \param	startY  	The start y coordinate.
 * \param	binColor	If non-null, the bin color.
 */

Bin::Bin(int startX, int startY, BinColor binColor)
: GUIBase()
{
	currentFeeder = NULL;

	switch (binColor)
	{
	case BinColor_White:	loadImage("Resources/Sprites/Bin/Bin1.png");  break;
	case BinColor_Purple:	loadImage("Resources/Sprites/Bin/Bin2.png");  break;
	case BinColor_Yellow:	loadImage("Resources/Sprites/Bin/Bin3.png");  break;
	case BinColor_Orange:	loadImage("Resources/Sprites/Bin/Bin4.png");  break;
	case BinColor_Green:	loadImage("Resources/Sprites/Bin/Bin5.png");  break;
	case BinColor_Pink:		loadImage("Resources/Sprites/Bin/Bin6.png");  break;
	case BinColor_Red:		loadImage("Resources/Sprites/Bin/Bin7.png");  break;
	case BinColor_Blue:		loadImage("Resources/Sprites/Bin/Bin8.png");  break;
	}

	this->setOriginCenter(); // Change origin to center of image.

	this->setX(startX);
	this->setY(startY);
	this->setZValue(ZVALUE_BIN);
}

/**
 * \fn	Bin::Bin(int startX, int startY, PartType partType, BinColor binColor)
 *
 * \brief	Constructor.
 *
 * \author	Andrew
 * \date	11/11/2011
 *
 * \param	startX  	The start x coordinate.
 * \param	startY  	The start y coordinate.
 * \param	partType	Type of the part.
 * \param	binColor	If non-null, the bin color.
 */

Bin::Bin(int startX, int startY, PartType partType, BinColor binColor)
: GUIBase()
{
	Bin(startX, startY, binColor);
	this->FillBinWithNewParts(partType);
}

/**
 * \fn	PartType Bin::GetPartType()
 *
 * \brief	Gets the part type.
 *
 * \author	Andrew
 * \date	11/11/2011
 *
 * \return	The part type.
 */

PartType Bin::GetPartType()
{
	if (parts.empty())
		return EMPTY;

	return parts.front()->partType;
}

/**
 * \fn	int Bin::GetPartCount()
 *
 * \brief	Gets the part count.
 *
 * \author	Andrew
 * \date	11/22/2011
 *
 * \return	The part count.
 */

int Bin::GetPartCount()
{
	return parts.size();
}

void Bin::beganAscending(qreal newScale, qreal scaleSpeed)
{
	this->setScaleSpeed(scaleSpeed);
	this->scaleOverTime(newScale);
	emit signalBeginAscending(1.3, scaleSpeed);
}

void Bin::beganDescending(qreal newScale, qreal scaleSpeed)
{
	this->setScaleSpeed(scaleSpeed);
	this->scaleOverTime(newScale);
	emit signalBeginDescending(1.0, scaleSpeed);
}

/*

Don't like the effect.

void Bin::beganBeingMoved(qreal destX, qreal destY)
{
	this->setMovementSpeed(4.0);
	QGraphicsObject *binParent = (QGraphicsObject*)this->parentObject();
	if (binParent != NULL)
	{
		qreal vec[2];
		vec[0] = destX - binParent->x();
		vec[1] = destY - binParent->y();
		
		qreal dist = qSqrt(qPow(vec[0], 2) + qPow(vec[1], 2));
		vec[0] = vec[0] / dist * 20;
		vec[1] = vec[1] / dist * 20;

		moveTo(-vec[0], -vec[1]);
	}
}

void Bin::doneBeingMoved(qreal newX, qreal newY)
{
	moveTo(0, 0);
	//qDebug("stop");
}

*/

/**
 * \fn	void Bin::AddPartToBin(Part* part)
 *
 * \brief	Adds a part to bin.
 *
 * \author	Andrew
 * \date	11/11/2011
 *
 * \param [in,out]	part	If non-null, the part.
 */

void Bin::AddPartToBin(Part* part)
{
	parts.push_back(part);
	part->setFlag(QGraphicsItem::ItemStacksBehindParent, false);
	part->setParentItem(this);
	QObject::connect(this, SIGNAL(signalBeginAscending(qreal, qreal)), part, SLOT(beganAscending(qreal, qreal)));
	QObject::connect(this, SIGNAL(signalBeginDescending(qreal, qreal)), part, SLOT(beganDescending(qreal, qreal)));

	int randX = (rand() % 16) - 8;
	int randY = (rand() % 16) - 8;
	part->setPos(randX, randY);
}

/**
 * \fn	Part* Bin::TakeTopPartOut()
 *
 * \brief	Gets the take top part out.
 *
 * \author	Andrew
 * \date	11/11/2011
 *
 * \return	null if it fails, else.
 */

Part* Bin::TakeTopPartOut()
{
	if (!parts.empty())
	{
		Part* topPart = parts.front();
		parts.erase(parts.begin());
		topPart->setParentItem(NULL);
		topPart->setPos(this->scenePos().x(), this->scenePos().y());
		QObject::disconnect(SIGNAL(signalBeginAscending(qreal, qreal)), topPart, SLOT(beganAscending(qreal, qreal)));
		QObject::disconnect(SIGNAL(signalBeginDescending(qreal, qreal)), topPart, SLOT(beganDescending(qreal, qreal)));
		topPart->scaleOverTime(1.0);
		return topPart;
	}
	return NULL;
}

/**
 * \fn	void Bin::FillBinWithNewParts(PartType partType)
 *
 * \brief	Fill bin with new parts.
 *
 * \author	Andrew
 * \date	11/11/2011
 *
 * \param	partType	Type of the part.
 */

void Bin::FillBinWithNewParts(PartType partType)
{
	// Dump the contents.
	EmptyBin();

	// Create parts.
	for (int i = 0; i < PARTS_PER_BIN; i++)
	{
		this->AddPartToBin(new Part(0, 0, partType, scene()));
	}
}

/**
 * \fn	void Bin::EmptyBin()
 *
 * \brief	Empty bin.
 *
 * \author	Andrew
 * \date	11/11/2011
 */

void Bin::EmptyBin()
{
	//for (int i = 0; i < this->childItems().size(); i++)
	while (!parts.empty())
		this->TakeTopPartOut();
}

/**
 * \fn	vector<Part*> Bin::GetParts()
 *
 * \brief	Gets the parts.
 *
 * \author	Andrew
 * \date	11/11/2011
 *
 * \return	null if it fails, else the parts.
 */

vector<Part*> Bin::GetParts()
{
	return parts;
}

/**
 * \fn	void Bin::SetFeeder(GUIFeeder *feeder)
 *
 * \brief	Sets a feeder.
 *
 * \author	Andrew
 * \date	11/18/2011
 *
 * \param [in,out]	feeder	If non-null, the feeder.
 */

void Bin::SetFeeder(GUIFeeder *feeder)
{
	currentFeeder = feeder;
}

/**
 * \fn	GUIFeeder* Bin::GetFeeder()
 *
 * \brief	Gets the feeder.
 *
 * \author	Andrew
 * \date	11/18/2011
 *
 * \return	null if it fails, else the feeder.
 */

GUIFeeder* Bin::GetFeeder()
{
	return currentFeeder;
}
